//
//  main.c
//  The_Set
//
//  Created by Роман Ануфриев on 17.04.14.
//  Copyright (c) 2014 Роман Ануфриев. All rights reserved.
//

#include <stdio.h>
#include <string.h>
#include "The_Set.h"

#define PRINT_VAR_NAME(x) printf(#x)
#define PRINT_ALL_POSSIBLE_COMMANDS \
                          printf ("\n"                                    ); \
                          printf ("\t1) Add an element to a set;\n"       ); \
						  printf ("\t2) Delete an element from a set;\n"  ); \
						  printf ("\t3) Delete all elements from a set;\n"); \
						  printf ("\t4) Print contents of a set;\n"       ); \
						  printf ("\t5) Print the list of all commands\n" ); \
						  printf ("\t6) Exit the program.\n"              ); \
						  printf ("\n"                                    )


void theSet_print (struct theSet_elem* theSet_head, int numb_of_set);

int compare (const void* p1, const void* p2);

struct girl
	{
	int bust;
	int waist;
	int hip;
	} sample_girl;

int main()
{
	enum boolean ret_val = false;
	int i = 0, numbOfSets = 0, numb_of_set = 0, numb_of_action = 0,
		bust = 0, waist = 0, hip = 0;
	
	struct theSet_elem **array_of_theSets = NULL;
	
		
	printf ("With how many sets do you want to work?\n"  );
		
	while (1)
		{
		printf ("Number of sets: ");
		scanf  ("%d", &numbOfSets );
		printf ("\n"              );
		
		if (numbOfSets > 0)
			{
			array_of_theSets = (struct theSet_elem**) calloc (numbOfSets, sizeof (struct theSet_elem*));
			assert (array_of_theSets);
			
			for (i = 0; i < numbOfSets; i++)
				theSet_construct (&array_of_theSets[i]);
			break;
			}
		else
			printf ("Maybe a positive integer number?\n");
		}
	
	printf ("\t\tWhat do you want to do next?\n");
	PRINT_ALL_POSSIBLE_COMMANDS;
	while (1)
		{
		printf ("Number of command (5 - to list all commands): ");
		scanf  ("%d", &numb_of_action                           );
		
		switch (numb_of_action)
			{
			case 1:
				{
				while (1)
					{
					printf ("In what set do you want to add an info?\n"    );
					printf ("Number of the set: "                          );
					scanf  ("%d", &numb_of_set                             );
					
					if (numb_of_set >= 0 && numb_of_set <= numbOfSets - 1)
						break;
					else
						{
						printf ("You entered wrong number!\n");
						printf ("Try again...\n\n"           );
						}
					}
					
				printf ("\n");
				printf ("Write an information about the girl:\n");
				printf ("bust  = "); scanf ("%d", &bust );
				printf ("waist = "); scanf ("%d", &waist);
				printf ("hip   = "); scanf ("%d", &hip  );
				
				sample_girl.bust  = bust;
				sample_girl.waist = waist;
				sample_girl.hip   = hip;
				
				ret_val = theSet_add (&array_of_theSets[numb_of_set],
									  &sample_girl,
									  sizeof (sample_girl),
									  compare);
				if (ret_val)
					printf ("Info about girl has been successfully added!\n\n");
				else
					printf ("Info about girl has not been added!\n\n"         );
				
				break;
				}
			
			case 2:
				{
				while (1)
					{
					printf ("From what set do you want to delete a girl?\n");
					printf ("Number of the set: "                          );
					scanf  ("%d", &numb_of_set                             );
					
					if (numb_of_set >= 0 && numb_of_set <= numbOfSets - 1)
						break;
					else
						{
						printf ("You entered wrong number!\n");
						printf ("Try again...\n\n"           );
						}
					}
					
				printf ("\n");
				printf ("Write an information about the girl being deleted:\n");
				printf ("bust  = "); scanf ("%d", &bust );
				printf ("waist = "); scanf ("%d", &waist);
				printf ("hip   = "); scanf ("%d", &hip  );
				
				sample_girl.bust  = bust;
				sample_girl.waist = waist;
				sample_girl.hip   = hip;
				
				ret_val = theSet_delete (&array_of_theSets[numb_of_set],
				                         &sample_girl,
										 sizeof (sample_girl),
										 compare);
				
				if (ret_val)
					printf ("Info about girl has been successfully deleted!\n\n");
				else
					printf ("Info about girl has not been deleted!\n\n"         );
				
				break;
				}
			
			case 3:
				{
				while (1)
					{
					printf ("What set do you want to clean up?\n"          );
					printf ("Number of the set: "                          );
					scanf  ("%d", &numb_of_set                             );
					
					if (numb_of_set >= 0 && numb_of_set <= numbOfSets - 1)
						break;
					else
						{
						printf ("You entered wrong number!\n");
						printf ("Try again...\n\n"           );
						}
					}
				theSet_destruct  (&array_of_theSets[numb_of_set]);
				theSet_construct (&array_of_theSets[numb_of_set]);
				
				printf ("theSet has been successfully cleaned up!\n\n");
				
				break;
				}
				
			case 4:
				{
				while (1)
					{
					printf ("What set do you want to print?\n");
					printf ("Number of the set: "             );
					scanf  ("%d", &numb_of_set                );
					
					if (numb_of_set >= 0 && numb_of_set <= numbOfSets - 1)
						break;
					else
						{
						printf ("You entered wrong number!\n");
						printf ("Try again...\n\n"           );
						}
					}
					
				theSet_print (array_of_theSets[numb_of_set], numb_of_set);
				
				break;
				}
				
			case 5:
				{
				PRINT_ALL_POSSIBLE_COMMANDS;
				break;
				}
			case 6:
				break;
			
			default:
				{
				printf ("You entered wrong command!\n\n");
				break;
				}
			}
		if (numb_of_action == 6)
			break;
		}
	
	printf ("\n\n\t" "Thank you for using my program!" "\n\n");
	
	
	// freeing allocated memory
	for (i = 0; i < numbOfSets; i++)
		{
		theSet_destruct(&array_of_theSets[i]);
		}
	
	free (array_of_theSets); array_of_theSets = NULL;
	return 0;
}

void theSet_print (struct theSet_elem* theSet_head, int numb_of_set)
	{
	int i = 0;
	struct theSet_elem *curr = NULL;
	
	if (!theSet_head)
		{
		printf ("theSet is empty.\n\n");
		}
	else
		{
		curr = theSet_head;
		printf ("\n=====================\n"     );
		printf ("\t" "theSet №%d\n", numb_of_set);
		while (curr)
			{
			printf ("\n---------------------\n"                               );
			printf ("bust  = %d;\n", ((struct girl*)(curr -> elem_t)) -> bust );
			printf ("waist = %d;\n", ((struct girl*)(curr -> elem_t)) -> waist);
			printf ("hip   = %d;"  , ((struct girl*)(curr -> elem_t)) -> hip  );
			printf ("\n---------------------\n"                               );
			
			curr = curr -> next;
			i++;
			}
		printf ("\n=====================\n");
		}
		
	}

int compare (const void* p1, const void* p2)
	{
	int std_bust  = 90,
		std_waist = 60,
		std_hip   = 90,
		
		std_deviation1 = 0,
		std_deviation2 = 0,
		
		deviat_of_b = 0,
		deviat_of_w = 0,
		deviat_of_h = 0;
	
	// for 1st girl
	deviat_of_b = std_bust  - ((struct girl*)p1) -> bust;
	deviat_of_w = std_waist - ((struct girl*)p1) -> waist;
	deviat_of_h = std_hip   - ((struct girl*)p1) -> hip;
	
	std_deviation1 = deviat_of_b * deviat_of_b +
	                 deviat_of_w * deviat_of_w +
					 deviat_of_h * deviat_of_h;
	
	// for 2nd girl
	deviat_of_b = std_bust  - ((struct girl*)p2) -> bust;
	deviat_of_w = std_waist - ((struct girl*)p2) -> waist;
	deviat_of_h = std_hip   - ((struct girl*)p2) -> hip;
	
	std_deviation2 = deviat_of_b * deviat_of_b +
	                 deviat_of_w * deviat_of_w +
					 deviat_of_h * deviat_of_h;
	
	return std_deviation1 - std_deviation2;
	}

